﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WindowSystem;
using WindowsGame.Ui;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using RoundLineCode;
using InputEventSystem;
using GameObjects;

namespace WindowsGame
{
    public class MapEditor
    {
        Window optionsWindow, terrainWindow, mapWindow;
        RadioGroup terrainTypesRadioGroup, editOptionsRadioGroup;
        Game1 game;
        private GUIManager gui;
        GameState gameState;
        TextBox mapName, mapWidth, mapHeight;

        List<Window> windows;

        const string alterTerrain = "Alter Terrain";
        const string layRoad = "Lay Road";

        Hex origin;

        public MapEditor(Game1 game, GUIManager gui, GameState gameState)
        {
            this.game = game;
            this.gui = gui;
            this.gameState = gameState;

            game.gameMode = Game1.GameMode.EditMap;

            editOptionsRadioGroup = new RadioGroup(game, gui)
            {
                X = 10,
                Y = 10,
                Width = 150,
                Height = 100,
            };

            var rb = new RadioButton(game, gui) { Text = alterTerrain, Y = 0, Checked = true };


            editOptionsRadioGroup.Add(rb);
            editOptionsRadioGroup.Add(new RadioButton(game, gui) { Text = layRoad, Y = 20 });

            optionsWindow = new Window(game, gui)
            {
                TitleText = "Options",
                X = game.Graphics.PreferredBackBufferWidth - 175,
                Y = 50,
                Width = 150,
                Height = 100,
            };
            optionsWindow.Add(editOptionsRadioGroup);

            gui.Add(optionsWindow);


            terrainTypesRadioGroup = new RadioGroup(game, gui)
            {
                X = 10,
                Y = 10,
                Width = 100,
                Height = (gameState.MapView.TerrainTypes.Count * 20) + 50,
            };

            for (var i = 0; i < gameState.MapView.TerrainTypes.Count; i++)
            {
                terrainTypesRadioGroup.Add(new RadioButton(game, gui) { Text = gameState.MapView.TerrainTypes.ElementAt(i).Name, Y = i * 20 });
            }

            terrainWindow = new Window(game, gui)
            {
                TitleText = "Terrain",
                X = game.Graphics.PreferredBackBufferWidth - 175,
                Y = 200,
                Width = 100,
                Height = (gameState.MapView.TerrainTypes.Count * 20) + 50,
            };
            terrainWindow.Add(terrainTypesRadioGroup);

            gui.Add(terrainWindow);


            mapWindow = new Window(game, gui)
            {
                TitleText = "Map",
                X = game.Graphics.PreferredBackBufferWidth - 175,
                Y = 500,
                Width = 100,
                Height = 170,
            };


            mapWindow.Add(new Label(game, gui) { Text = "Name", X = 10, Y = 15, Width = 100, Height = 20, });
            mapName = new TextBox(game, gui)
            {
                X = 50,
                Y = 10,
                Width = 100,
                Text = gameState.MapView.Name,
            };
            mapWindow.Add(mapName);

            mapWindow.Add(new Label(game, gui) { Text = "Width", X = 10, Y = 45, Width = 100, Height = 20, });
            mapWidth = new TextBox(game, gui)
            {
                X = 50,
                Y = 40,
                Width = 50,
                Text = gameState.MapView.Board.Width.ToString(),
            };
            mapWidth.KeyDown += (width_KeyDown);
            mapWindow.Add(mapWidth);

            mapWindow.Add(new Label(game, gui) { Text = "Height", X = 10, Y = 75, Width = 100, Height = 20, });
            mapHeight = new TextBox(game, gui)
            {
                X = 50,
                Y = 70,
                Width = 50,
                Text = gameState.MapView.Board.Height.ToString(),
            };
            mapHeight.KeyDown += (height_KeyDown);
            mapWindow.Add(mapHeight);


            var saveButton = new TextButton(game, gui) { Text = "Save", X = 5, Y = 105, };
            saveButton.Click += (saveButton_Click);
            mapWindow.Add(saveButton);

            gui.Add(mapWindow);


            windows = new List<Window> { optionsWindow, terrainWindow, mapWindow };

            //optionsWindow.
            //optionsWindow.MouseOver += new MouseOverHandler(optionsWindow_MouseOver);            
        }

        bool MouseOverDialogs
        {
            get
            {
                return windows.Where(o => o.IsMouseOver).Count() > 0;
            }
        }

        void height_KeyDown(KeyEventArgs args)
        {
            if (string.IsNullOrEmpty(mapHeight.Text) || mapHeight.Text == gameState.MapView.Board.Height.ToString()) return;

            var minBoardY = gameState.ActiveUnits.Count() == 0 ? 1 : gameState.ActiveUnits.Max(o => o.Location.Y);

            try
            {
                gameState.MapView.Board.Height = (int)MathHelper.Clamp(Convert.ToSingle(mapHeight.Text), minBoardY, 100);
                game.CreateHexes();
            }
            catch (Exception)
            {
                
            }
            mapHeight.Text = gameState.MapView.Board.Height.ToString();
        }

        void width_KeyDown(KeyEventArgs args)
        {
            if (string.IsNullOrEmpty(mapWidth.Text) || mapWidth.Text == gameState.MapView.Board.Width.ToString())
                return;

            var minBoardX = gameState.ActiveUnits.Count() == 0 ? 1 : gameState.ActiveUnits.Max(o => o.Location.X);

            try
            {
                gameState.MapView.Board.Width = (int)MathHelper.Clamp(Convert.ToSingle(mapWidth.Text), minBoardX, 100);
                game.CreateHexes();
            }
            catch (Exception)
            {
                
            }
            mapWidth.Text = gameState.MapView.Board.Width.ToString();
        }

        void saveButton_Click(UIComponent sender)
        {
            //gameState.SaveMap(mapName.Text);
            Close();
        }

        internal string SelectedTerrainType()
        {
            var selectedRadioButton = terrainTypesRadioGroup.Items.SingleOrDefault(o => o.Checked);
            if (selectedRadioButton == null)
                return null;
            return selectedRadioButton.Text;
        }


        internal void Close()
        {
            optionsWindow.CloseWindow();
            terrainWindow.CloseWindow();
            mapWindow.CloseWindow();
            game.gameMode = Game1.GameMode.Play;
        }

        internal void Input(Cursor cursor, IList<UiHex> highlightedHexes)
        {
            switch (editOptionsRadioGroup.Items.Single(o => o.Checked).Text)
            {
                case alterTerrain:
                    origin = null;
                    if (cursor.MouseButtonRelease(MouseButtons.LeftButton) && !MouseOverDialogs)
                    {
                        if (highlightedHexes.Count() == 1)
                        {
                            var terrainType = SelectedTerrainType();
                            //if (!string.IsNullOrEmpty(terrainType))
                                //highlightedHexes[0].Hex.Target.TerrainType(gameState.GetWeather(highlightedHexes[0].Hex.Target)) = gameState.TerrainTypes.Single(o => o.Name == terrainType);
                        }
                    }
                    break;
                case layRoad:
                    game.TempLines = new List<RoundLine>();

                    if (highlightedHexes.Count == 0)
                        return;

                    var destination = highlightedHexes[0].Hex.Target;

                    if (gameState.HexTerrainType(destination).MovementType == MetaData.MoveType.Water)
                        return;

                    if (cursor.MouseButtonRelease(MouseButtons.LeftButton) && !MouseOverDialogs)
                    {
                        if (origin == null)
                        {
                            if (gameState.HexTerrainType(highlightedHexes[0].Hex.Target).MovementType == MetaData.MoveType.Water)
                                return;

                            origin = highlightedHexes[0].Hex.Target;
                            return;
                        }

                        if (gameState.AreAdjacentCells(origin, destination))
                        {
                            var vector = gameState.GetVector(origin, destination);
                            if (vector != null)
                                gameState.MapView.Vectors.Remove(vector);
                            else
                                gameState.MapView.Vectors.Add(new Vector(MetaData.VectorType.Road, origin, destination, gameState.MapView.Vectors.Count + 1));

                            game.LoadLines();
                            origin = null;
                        }
                        else
                            origin = destination;
                    }
                    else
                    {
                        if (origin == null || !gameState.AreAdjacentCells(origin, destination))
                            return;

                        var hex1 = game.GetXYZForHexRowAndCol(Game1.HexSpacing, Convert.ToInt16(origin.X), Convert.ToInt16(origin.Y));
                        var hex2 = game.GetXYZForHexRowAndCol(Game1.HexSpacing, Convert.ToInt16(destination.X), Convert.ToInt16(destination.Y));

                        game.TempLines.Add(new RoundLine(hex1.X, hex1.Y, hex2.X, hex2.Y));
                    }
                    break;
            }


        }
    }
}
